--
-- Rotor module interface definition
--

--
-- Local refrences to global objects
--
local Rotor = _G.Rotor

local RotorModule = {}

--
-- Answer module name
--
-- arguments:
--      none
--  returns:
--      module name <string>
--
function RotorModule:Name()
    return self.module_name
end

--
-- Register module within Rotor
--
-- arguments:
--      none
-- returns:
--      none
--
function RotorModule:Register()
    Rotor:RegisterModule(self)
end

--
-- Unregister module from Rotor
--
function RotorModule:Unregister()
    Rotor:UnregisterModule(self)
end

--
-- Detect module usability for current spec
--
function RotorModule:Detect()
    return false
end

--
-- Initialize module
--
-- arguments:
--      options<table> - table of module options (persist between logons)
-- return:
--      true - module successfully initialized
--      false/nil, failure_reason<string> - initialization failed. failure_reason is optional
--
function RotorModule:Init(options)
    return nil, 'Init function is not defined for module "'..self:Name()..'"'
end

--
-- Finalize module before switching to new (possible this) module
--
-- arguments:
--      new_module - module which will be used after this module (may be this module)
-- returns:
--      none
function RotorModule:Done(new_module)
end

--
-- Choose next skill
--
-- arguments:
--      gcd<float> - remain GCD time in seconds with fractional part
--      cur_skill - currently displayed skill, still waiting to send or 0 if send wait is over
-- return
--      next skill ID or 0 if no next skill
--
function RotorModule:NextSkill(gcd, cur_skill)
    return 0
end

--
-- Notify module about sent cast
--
-- arguments:
--      spell_name<string> - the name of sent spell
--      spell_rec -- sent spell record if any
-- return:
--      none
--
function RotorModule:CastSent(spell_name, spell_rec)
end

--
-- Notify module about send done (UNIT_SPELLCAST_SUCCEED, UNIT_SPELLCAST_FAILED, UNIT_SPELLCAST_INTERRUPTED, UNIT_SPELLCAST_FAILED_QUIET)
--
-- arguments:
--      spell_name - the name of finished spell
--      is_success - true if sent successfull, false otherwise
--      failire_reason - on failed cast one of following: FAILED_QUIET, FAILED, INTERRUPTED, DELAYED (depends on event type)
--      spell_rec -- finished spell record if any
-- return:
--      false/nil if next spell SHOULD be chosen
--
function RotorModule:CastFinished(spell_name, is_success, failure_reason, spell_rec)
    return false
end

--
-- Update function. Called when frame OnUpdate event occured.
--
-- arguments:
--      elapsed<float> - time in seconds since last call to Update
-- return:
--      none
--
function RotorModule:Update(elapsed)
end

--
-- Notify module about inventory change.
--
-- arguments:
--      none
-- return:
--      true if next skill should be chosen, false otherwise
--
function RotorModule:InventoryChanged()
    return false
end

--
-- Notify module about target changed.
--
-- arguments:
--      old_target_guid - GUID of previous valid target
-- return:
--      none
function RotorModule:TargetChanged(old_target_guid)
end

--
-- Notify module when unit is entering or leaving combat
--
-- arugments:
--      none
-- return:
--      none
--
function RotorModule:CombatStateChanged()
end

--
-- Called when spell usablity needed to be checked.
--
-- arguments:
--      spell_id - id of spell being checked (usually currently suggested spell)
-- return:
--      true - spell is usable, false otherwise
--
function RotorModule:CheckUsable(spell_id)
    return Rotor:defaultUsableCheck(spell_id)
end

--
-- Called when spell range needed to be checked.
--
-- arguments:
--      spell_id - id of spell being checked (usually currently suggested spell)
-- return:
--      true - spell is in range (or range is not important), false otherwise
--
function RotorModule:CheckInRange(spell_id)
    return Rotor:defaultRangeCheck(spell_id)
end

--
-- Handle commands from command line. called when /rr opt ... is executed
--
-- arguments:
--      cmd_line<string> - text after '/rr opt'
-- return:
--      true - module reinitialization required, false otherwise
--
function RotorModule:HandleCommandLine(cmd_line)
    Rotor:print('Module "'..self:Name()..'" does not have options')
    return false
end

--
-- Answer time to wait for send suggested spell after gcd ends.
--
-- arguments:
--      spell_id - id of current spell
-- returns:
--      time in seconds to wait or nil if use default time
--
function RotorModule:TimeToWaitOfSend(spell_id)
    return nil
end

--
-- Sent when all resources and all cooldowns and all auras is updated
--
function RotorModule:SpellsAurasAndResourcesUpdated()
end

----------------------------------------
--
-- Create and register new rotation module
--
function Rotor:NewModule(mod_name)

    if not mod_name then
        error('no module name given')
    end

    if self.modules[mod_name] then
        error('module "'..mod_name..'" alredy exists')
    end

    local m = setmetatable({module_name = mod_name}, {__index = RotorModule})

    self.modules[mod_name] = m
    return m
end
